一口氣讀完了兩個章節,是否開始感到混亂了呢?感謝這個科技的時代,可以請 AI 協助出題複習知識點,並精選重要概念做個階段性的檢核。讓我們一起溫故而知新,針對不熟悉的觀念查缺補漏吧!
Q1. 在使用 STL 的 iterator 和 function object 時,通常會用哪種方式傳遞參數?
A) Pass-by-reference-to-const。
B) Pass-by-pointer。
C) Pass-by-reference。
D) Pass-by-move。
E) Pass-by-value。
在 STL 中,iterator 和 function object 的設計是基於 C 語言的指標,因此依然適用 pass-by-value 規則。這種方式可有效提高安全性,避免因指標或引用錯誤造成原始物件被修改。
STL 是 C++ 的重要工具,由 container、iterator、algorithm、function object 組成。Iterator 用來指向 container 內的元素,並提供遍歷這些元素的功能。Function object 也稱為 functor,允許我們像函式那樣操作物件。
對於 container 等較大型的物件,則通常會選擇 pass-by-reference 的方式,確保程式的性能。
Q2. 在某些編譯器上,以下這段程式碼可能無法編譯:
class StudentYoyo {
private:
static const int subject = 5;
int scores[subject];
};
如何確保 subject
作為 array size 能在所有編譯器上正確運作?
A) 宣告 subject
為 non-static 成員。
B) 使用 #define
定義 subject
。
C) 將 subject
改為非 const
的靜態成員。
D) 在 class 內使用 enum { subject = 5 };
E) 將 subject
宣告為 extern
。
enum
是一種廣泛的解法,能確保陣列大小設定等常數可在編譯時使用,並能適用於所有編譯器。
在 C++ 中,陣列的大小必須是 compile-time constant。在此題 subject
被宣告為 static const
成員。雖然理論上是一個常數,然而某些舊式編譯器無法正常處理。
enum
仍作用於 class 內部,不會污染到其他 namespace
。這種技術被稱為 Enum Hack。
Non-static 成員的值必須依賴 object 的實例,無法在編譯時確定,因此不適合用於陣列大小。使用 #define
可以提供 compile-time constant,但會污染 namespace
。extern
表示變數是外部的,通常需在執行時決定其值。
Q1. 關於 copy assignment operator 呼叫 copy constructor,下列敘述何者正確?
A) 這類做法可以有效避免程式碼重複。
B) 有可能會造成異常,應避免這種情境。
C) 這是 C 語言白皮書強烈推薦的寫法。
D) 只有包含簡單資料成員的 class 才可以這麼做。
E) 是可以確保 exception-safe 的唯一方法。
copy assignment operator 和 copy constructor 的語意不同,這樣做可能會導致物件出現不正確或未定義的行為。
知識點 5 及知識點 12 都有強調過,copy constructor 會先建立一個全新的 object,copy assignment operator 則用於將來源物件的狀態賦值給一個已存在的 object。
Q2. 以下類別中,針對解構子內的 close()
函式可能拋出的 exception,應採用何種處理方式?
class DBConn {
public:
~DBConn() { db.close(); }
private:
DBConnection db;
};
A) 讓 exception 自然地從解構子傳播出去。
B) 忽略 exception 的可能性,因為解構子不應該失敗。
C) 以 static
變數追蹤 exception。
D) 選擇吞下 exception 或終止程式。
E) 增加 throw()
規範來宣告解構子。
解構子應該捕捉由
close()
函式拋出的 exception,有幾種常見的處理方式:
- 吞下 exception。 e.g. 記錄錯誤
- 主動終止程式。 e.g. 調用
std::abort
。
解構子通常在 object 範圍結束或因 exception 而進行 stack unwinding 時被調用。此時程式已進入清理階段,解構子拋出 exception 可能會導致資源泄漏。若在 stack unwinding 期間重複拋出 exception,程式可能會因同時有多個 exception 而導致而強制 std::terminate
。
現代 C++ 不建議使用 throw()
的方式,且無法完全避免解構子拋 exception 的問題。